#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""配置管理API路由模块"""

from flask import Blueprint, request, jsonify
import yaml
import json
import os
from functools import wraps
import logging
from datetime import datetime

# 导入数据库服务
from database import get_db_service
from .auth import token_required

# 创建蓝图
configs_bp = Blueprint('configs', __name__)

# 获取数据库服务实例
db_service = get_db_service()

# 配置日志
logger = logging.getLogger(__name__)

# 配置文件路径
CONFIG_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'config'))
CONFIG_FILE = os.path.join(CONFIG_DIR, 'config.yaml')
CAMERA_CONFIG_FILE = os.path.join(CONFIG_DIR, 'camera_config.json')


def log_api_access(f):
    """记录API访问的装饰器"""
    @wraps(f)
    def decorated(*args, **kwargs):
        logger.info(f"API访问: {request.method} {request.path}")
        return f(*args, **kwargs)
    return decorated


def admin_required(f):
    """管理员权限装饰器"""
    @wraps(f)
    @token_required
    def decorated(*args, **kwargs):
        if not hasattr(request, 'current_user'):
            return jsonify({
                'success': False,
                'data': None,
                'message': '用户认证失败'
            }), 401
        
        if not request.current_user.is_admin:
            return jsonify({
                'success': False,
                'data': None,
                'message': '需要管理员权限'
            }), 403
        
        return f(*args, **kwargs)
    return decorated


def read_yaml_config(file_path):
    """读取YAML配置文件"""
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            return yaml.safe_load(f)
    except Exception as e:
        logger.error(f"读取YAML配置文件失败: {str(e)}")
        return {}


def write_yaml_config(file_path, config_data):
    """写入YAML配置文件"""
    try:
        # 确保目录存在
        os.makedirs(os.path.dirname(file_path), exist_ok=True)
        
        with open(file_path, 'w', encoding='utf-8') as f:
            yaml.dump(config_data, f, default_flow_style=False, allow_unicode=True)
        return True
    except Exception as e:
        logger.error(f"写入YAML配置文件失败: {str(e)}")
        return False


def read_json_config(file_path):
    """读取JSON配置文件"""
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            return json.load(f)
    except Exception as e:
        logger.error(f"读取JSON配置文件失败: {str(e)}")
        return {}


def write_json_config(file_path, config_data):
    """写入JSON配置文件"""
    try:
        # 确保目录存在
        os.makedirs(os.path.dirname(file_path), exist_ok=True)
        
        with open(file_path, 'w', encoding='utf-8') as f:
            json.dump(config_data, f, indent=2, ensure_ascii=False)
        return True
    except Exception as e:
        logger.error(f"写入JSON配置文件失败: {str(e)}")
        return False


@configs_bp.route('/configs', methods=['GET'])
@token_required
@log_api_access
def get_all_configs():
    """获取所有配置项"""
    try:
        # 从数据库获取配置
        configs = db_service.get_all_configs()
        
        # 构建配置字典
        config_dict = {}
        for config in configs:
            config_dict[config.key] = {
                'value': config.value,
                'type': config.type,
                'description': config.description,
                'category': config.category,
                'is_editable': config.is_editable,
                'created_at': config.created_at.isoformat() if config.created_at else None,
                'updated_at': config.updated_at.isoformat() if config.updated_at else None
            }
        
        return jsonify({
            'success': True,
            'data': config_dict,
            'message': '配置获取成功'
        })
        
    except Exception as e:
        logger.error(f"获取配置失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'获取配置失败: {str(e)}'
        }), 500


@configs_bp.route('/configs/<string:config_key>', methods=['GET'])
@token_required
@log_api_access
def get_config(config_key):
    """获取指定配置项"""
    try:
        # 从数据库获取配置
        config = db_service.get_config_by_key(config_key)
        
        if not config:
            return jsonify({
                'success': False,
                'data': None,
                'message': '配置项不存在'
            }), 404
        
        # 构建响应数据
        config_data = {
            'key': config.key,
            'value': config.value,
            'type': config.type,
            'description': config.description,
            'category': config.category,
            'is_editable': config.is_editable,
            'created_at': config.created_at.isoformat() if config.created_at else None,
            'updated_at': config.updated_at.isoformat() if config.updated_at else None
        }
        
        return jsonify({
            'success': True,
            'data': config_data,
            'message': '配置获取成功'
        })
        
    except Exception as e:
        logger.error(f"获取配置失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'获取配置失败: {str(e)}'
        }), 500


@configs_bp.route('/configs/category/<string:category>', methods=['GET'])
@token_required
@log_api_access
def get_configs_by_category(category):
    """按类别获取配置项"""
    try:
        # 从数据库获取配置
        configs = db_service.get_configs_by_category(category)
        
        # 构建配置字典
        config_dict = {}
        for config in configs:
            config_dict[config.key] = {
                'value': config.value,
                'type': config.type,
                'description': config.description,
                'is_editable': config.is_editable,
                'created_at': config.created_at.isoformat() if config.created_at else None,
                'updated_at': config.updated_at.isoformat() if config.updated_at else None
            }
        
        return jsonify({
            'success': True,
            'data': {
                'category': category,
                'configs': config_dict
            },
            'message': '配置获取成功'
        })
        
    except Exception as e:
        logger.error(f"获取配置失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'获取配置失败: {str(e)}'
        }), 500


@configs_bp.route('/configs/<string:config_key>', methods=['PUT'])
@admin_required
@log_api_access
def update_config(config_key):
    """更新配置项"""
    try:
        # 解析请求体
        data = request.get_json() or {}
        value = data.get('value')
        
        if value is None:
            return jsonify({
                'success': False,
                'data': None,
                'message': '配置值不能为空'
            }), 400
        
        # 检查配置是否可编辑
        config = db_service.get_config_by_key(config_key)
        if not config:
            return jsonify({
                'success': False,
                'data': None,
                'message': '配置项不存在'
            }), 404
        
        if not config.is_editable:
            return jsonify({
                'success': False,
                'data': None,
                'message': '该配置项不可编辑'
            }), 403
        
        # 更新配置
        success = db_service.update_config(config_key, value)
        
        if success:
            # 记录配置变更日志
            user_id = request.current_user.id if hasattr(request, 'current_user') else None
            db_service.add_system_log(
                level='INFO',
                component='config',
                message=f'配置更新: {config_key} = {value}',
                metadata={'user_id': user_id, 'action': 'config_update'}
            )
            
            return jsonify({
                'success': True,
                'data': None,
                'message': '配置更新成功'
            })
        else:
            return jsonify({
                'success': False,
                'data': None,
                'message': '配置更新失败'
            }), 500
            
    except Exception as e:
        logger.error(f"更新配置失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'更新配置失败: {str(e)}'
        }), 500


@configs_bp.route('/configs/batch', methods=['PUT'])
@admin_required
@log_api_access
def batch_update_configs():
    """批量更新配置项"""
    try:
        # 解析请求体
        data = request.get_json() or {}
        updates = data.get('updates', {})
        
        if not isinstance(updates, dict):
            return jsonify({
                'success': False,
                'data': None,
                'message': '更新数据格式错误'
            }), 400
        
        if not updates:
            return jsonify({
                'success': False,
                'data': None,
                'message': '没有需要更新的配置'
            }), 400
        
        updated_count = 0
        errors = []
        
        # 批量更新配置
        for config_key, value in updates.items():
            # 检查配置是否可编辑
            config = db_service.get_config_by_key(config_key)
            if not config:
                errors.append(f'配置项 {config_key} 不存在')
                continue
            
            if not config.is_editable:
                errors.append(f'配置项 {config_key} 不可编辑')
                continue
            
            # 更新配置
            if db_service.update_config(config_key, value):
                updated_count += 1
            else:
                errors.append(f'配置项 {config_key} 更新失败')
        
        # 记录配置变更日志
        if updated_count > 0:
            user_id = request.current_user.id if hasattr(request, 'current_user') else None
            db_service.add_system_log(
                level='INFO',
                component='config',
                message=f'批量更新配置: 成功 {updated_count} 项',
                metadata={'user_id': user_id, 'action': 'config_batch_update', 'updates': list(updates.keys())[:10]}
            )
        
        return jsonify({
            'success': updated_count > 0,
            'data': {
                'updated_count': updated_count,
                'errors': errors
            },
            'message': f'成功更新 {updated_count} 项配置'
        })
        
    except Exception as e:
        logger.error(f"批量更新配置失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'批量更新配置失败: {str(e)}'
        }), 500


@configs_bp.route('/configs/system', methods=['GET'])
@token_required
@log_api_access
def get_system_config():
    """获取系统配置文件内容"""
    try:
        # 读取配置文件
        config_data = read_yaml_config(CONFIG_FILE)
        
        return jsonify({
            'success': True,
            'data': config_data,
            'message': '系统配置获取成功'
        })
        
    except Exception as e:
        logger.error(f"获取系统配置失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'获取系统配置失败: {str(e)}'
        }), 500


@configs_bp.route('/configs/system', methods=['PUT'])
@admin_required
@log_api_access
def update_system_config():
    """更新系统配置文件"""
    try:
        # 解析请求体
        config_data = request.get_json()
        
        if not config_data:
            return jsonify({
                'success': False,
                'data': None,
                'message': '配置数据不能为空'
            }), 400
        
        # 备份当前配置
        backup_path = f"{CONFIG_FILE}.{datetime.now().strftime('%Y%m%d_%H%M%S')}.bak"
        current_config = read_yaml_config(CONFIG_FILE)
        if current_config:
            write_yaml_config(backup_path, current_config)
        
        # 写入新配置
        if write_yaml_config(CONFIG_FILE, config_data):
            # 记录配置变更日志
            user_id = request.current_user.id if hasattr(request, 'current_user') else None
            db_service.add_system_log(
                level='INFO',
                component='config',
                message='系统配置文件已更新',
                metadata={'user_id': user_id, 'action': 'system_config_update', 'backup_file': backup_path}
            )
            
            return jsonify({
                'success': True,
                'data': {
                    'backup_file': backup_path
                },
                'message': '系统配置更新成功，旧配置已备份'
            })
        else:
            return jsonify({
                'success': False,
                'data': None,
                'message': '系统配置更新失败'
            }), 500
            
    except Exception as e:
        logger.error(f"更新系统配置失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'更新系统配置失败: {str(e)}'
        }), 500


@configs_bp.route('/configs/camera', methods=['GET'])
@token_required
@log_api_access
def get_camera_config():
    """获取摄像头配置文件内容"""
    try:
        # 读取摄像头配置文件
        camera_config = read_json_config(CAMERA_CONFIG_FILE)
        
        return jsonify({
            'success': True,
            'data': camera_config,
            'message': '摄像头配置获取成功'
        })
        
    except Exception as e:
        logger.error(f"获取摄像头配置失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'获取摄像头配置失败: {str(e)}'
        }), 500


@configs_bp.route('/configs/camera', methods=['PUT'])
@admin_required
@log_api_access
def update_camera_config():
    """更新摄像头配置文件"""
    try:
        # 解析请求体
        camera_config = request.get_json()
        
        if not camera_config:
            return jsonify({
                'success': False,
                'data': None,
                'message': '摄像头配置数据不能为空'
            }), 400
        
        # 备份当前配置
        backup_path = f"{CAMERA_CONFIG_FILE}.{datetime.now().strftime('%Y%m%d_%H%M%S')}.bak"
        current_config = read_json_config(CAMERA_CONFIG_FILE)
        if current_config:
            write_json_config(backup_path, current_config)
        
        # 写入新配置
        if write_json_config(CAMERA_CONFIG_FILE, camera_config):
            # 记录配置变更日志
            user_id = request.current_user.id if hasattr(request, 'current_user') else None
            db_service.add_system_log(
                level='INFO',
                component='config',
                message='摄像头配置文件已更新',
                metadata={'user_id': user_id, 'action': 'camera_config_update', 'backup_file': backup_path}
            )
            
            # 这里可以添加重新加载摄像头配置的逻辑
            # TODO: 触发摄像头配置重新加载
            
            return jsonify({
                'success': True,
                'data': {
                    'backup_file': backup_path
                },
                'message': '摄像头配置更新成功，旧配置已备份'
            })
        else:
            return jsonify({
                'success': False,
                'data': None,
                'message': '摄像头配置更新失败'
            }), 500
            
    except Exception as e:
        logger.error(f"更新摄像头配置失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'更新摄像头配置失败: {str(e)}'
        }), 500


@configs_bp.route('/configs/export', methods=['GET'])
@admin_required
@log_api_access
def export_configs():
    """导出所有配置"""
    try:
        # 获取所有配置
        configs = db_service.get_all_configs()
        system_config = read_yaml_config(CONFIG_FILE)
        camera_config = read_json_config(CAMERA_CONFIG_FILE)
        
        # 构建导出数据
        export_data = {
            'export_time': datetime.now().isoformat(),
            'version': '1.0',
            'database_configs': {},
            'system_config': system_config,
            'camera_config': camera_config
        }
        
        # 添加数据库配置
        for config in configs:
            export_data['database_configs'][config.key] = {
                'value': config.value,
                'type': config.type,
                'description': config.description,
                'category': config.category,
                'is_editable': config.is_editable
            }
        
        return jsonify({
            'success': True,
            'data': export_data,
            'message': '配置导出成功'
        })
        
    except Exception as e:
        logger.error(f"导出配置失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'导出配置失败: {str(e)}'
        }), 500


@configs_bp.route('/configs/import', methods=['POST'])
@admin_required
@log_api_access
def import_configs():
    """导入配置"""
    try:
        # 解析请求体
        import_data = request.get_json()
        
        if not import_data:
            return jsonify({
                'success': False,
                'data': None,
                'message': '导入数据不能为空'
            }), 400
        
        # 记录导入日志
        user_id = request.current_user.id if hasattr(request, 'current_user') else None
        import_log = {
            'level': 'INFO',
            'component': 'config',
            'message': '开始导入配置',
            'metadata': {
                'action': 'config_import',
                'user_id': user_id,
                'version': import_data.get('version'),
                'export_time': import_data.get('export_time')
            }
        }
        
        # 导入数据库配置
        db_configs = import_data.get('database_configs', {})
        db_config_count = 0
        
        for config_key, config_info in db_configs.items():
            # 检查是否存在
            existing = db_service.get_config_by_key(config_key)
            
            if existing:
                # 更新配置
                if config_info.get('is_editable', True):
                    db_service.update_config(
                        config_key,
                        config_info.get('value'),
                        config_info.get('type'),
                        config_info.get('description'),
                        config_info.get('category'),
                        config_info.get('is_editable')
                    )
                    db_config_count += 1
            else:
                # 创建新配置
                db_service.add_config(
                    key=config_key,
                    value=config_info.get('value'),
                    config_type=config_info.get('type', 'string'),
                    description=config_info.get('description', ''),
                    category=config_info.get('category', 'general'),
                    is_editable=config_info.get('is_editable', True)
                )
                db_config_count += 1
        
        # 导入系统配置
        system_config = import_data.get('system_config')
        system_config_updated = False
        
        if system_config:
            # 备份当前配置
            backup_path = f"{CONFIG_FILE}.import_{datetime.now().strftime('%Y%m%d_%H%M%S')}.bak"
            current_config = read_yaml_config(CONFIG_FILE)
            if current_config:
                write_yaml_config(backup_path, current_config)
            
            # 写入新配置
            system_config_updated = write_yaml_config(CONFIG_FILE, system_config)
        
        # 导入摄像头配置
        camera_config = import_data.get('camera_config')
        camera_config_updated = False
        
        if camera_config:
            # 备份当前配置
            backup_path = f"{CAMERA_CONFIG_FILE}.import_{datetime.now().strftime('%Y%m%d_%H%M%S')}.bak"
            current_config = read_json_config(CAMERA_CONFIG_FILE)
            if current_config:
                write_json_config(backup_path, current_config)
            
            # 写入新配置
            camera_config_updated = write_json_config(CAMERA_CONFIG_FILE, camera_config)
        
        # 更新导入日志
        import_log['message'] = '配置导入完成'
        import_log['metadata'].update({
            'db_configs_imported': db_config_count,
            'system_config_updated': system_config_updated,
            'camera_config_updated': camera_config_updated
        })
        
        db_service.add_system_log(**import_log)
        
        return jsonify({
            'success': True,
            'data': {
                'db_configs_imported': db_config_count,
                'system_config_updated': system_config_updated,
                'camera_config_updated': camera_config_updated
            },
            'message': '配置导入成功'
        })
        
    except Exception as e:
        logger.error(f"导入配置失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'导入配置失败: {str(e)}'
        }), 500


@configs_bp.route('/configs/categories', methods=['GET'])
@token_required
@log_api_access
def get_config_categories():
    """获取所有配置类别"""
    try:
        # 获取所有配置类别
        categories = db_service.get_all_config_categories()
        
        # 定义类别描述
        category_descriptions = {
            'general': '通用配置',
            'detection': '检测引擎配置',
            'tracking': '跟踪系统配置',
            'camera': '摄像头配置',
            'alert': '告警系统配置',
            'notification': '通知服务配置',
            'database': '数据库配置',
            'api': 'API服务配置',
            'system': '系统配置'
        }
        
        # 构建类别列表
        category_list = []
        for category in categories:
            category_list.append({
                'name': category,
                'description': category_descriptions.get(category, category)
            })
        
        return jsonify({
            'success': True,
            'data': {
                'categories': category_list
            },
            'message': '配置类别获取成功'
        })
        
    except Exception as e:
        logger.error(f"获取配置类别失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'获取配置类别失败: {str(e)}'
        }), 500